﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Text.RegularExpressions;

namespace ABII.AdminPanel
{
    public partial class AdminPanelForm : Form
    {
        public ConnectionState State { get; private set; }
        public Database Database { get; private set; }

        public AdminPanelForm()
        {
            InitializeComponent();
        }

        protected override CreateParams CreateParams {
            get {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }

        private void AdminPanelForm_Load(object sender, EventArgs e)
        {
            Database = new Database();
            State = ConnectionState.NONE;
            ChangeState(State);
            tbLoginServer.Text = Properties.Settings.Default.Server;
            tbLoginUsername.Text = Properties.Settings.Default.Username;
            tbLoginPassword.Text = Properties.Settings.Default.Password;
            udLoginTimeout.Text = Properties.Settings.Default.Timeout.ToString();
            chkbLoginRemember.Checked = Properties.Settings.Default.Remember;

            Connect();
        }

        private void btLoginConnect_Click(object sender, EventArgs e)
        {
            Connect();
        }

        private void Connect()
        {
            try
            {
                ChangeState(ConnectionState.AUTH);
                if (chkbLoginRemember.Checked)
                {
                    Properties.Settings.Default.Server = tbLoginServer.Text;
                    Properties.Settings.Default.Username = tbLoginUsername.Text;
                    Properties.Settings.Default.Password = tbLoginPassword.Text;
                    Properties.Settings.Default.Timeout = Convert.ToInt32(udLoginTimeout.Text);
                }
                Properties.Settings.Default.Remember = chkbLoginRemember.Checked;
                Properties.Settings.Default.Save();

                Database.Authenticate(tbLoginUsername.Text, tbLoginPassword.Text);

                Database.GetPublicData();

                ComboBoxFill(cbProcessRanks, Database.Ranks);
                UserlistFill(lvProcessUsers, Database.Users, Database.Ranks);

                ChangeState(ConnectionState.DONE);

            }
            catch(AuthenticationException ex)
            {
                Disconnect();
                MessageBox.Show(ex.ToString());
            }
        }

        private void ComboBoxFill(ComboBox control, List<Record> records)
        {
            control.BeginUpdate();
            control.Items.Clear();
            foreach (Record record in records)
            {
                control.Items.Add(record.Name);
            }
            if (control.Items.Count > 0)
            {
                control.SelectedIndex = 0;
            }
            control.EndUpdate();
        }

        private void UserlistFill(ListView control, List<Record> users, List<Record> ranks)
        {
            control.BeginUpdate();
            control.Items.Clear();
            foreach (Record rank in ranks)
            {
                control.Groups.Add(new ListViewGroup(rank.Name, HorizontalAlignment.Center));
            }
            foreach (Record record in users)
            {
                control.Items.Add(new ListViewItem(record.Name, FindGroup(control, ranks, record.ID)));;
            }
            if (control.Items.Count > 0)
            {
                control.Items[0].Selected = true;
            }
            control.EndUpdate();
        }

        private ListViewGroup FindGroup(ListView control, List<Record> ranks, Int32 id)
        {
            String name = ranks.Find(rank => rank.ID == id).Name;
            foreach (ListViewGroup group in control.Groups)
            {
                if (group.Header.Equals(name))
                {
                    return group;
                }
            }
            return null;
        }

        private void Disconnect()
        {
            Database.Disconnect();
            ChangeState(ConnectionState.NONE);
        }

        private void ChangeState(ConnectionState state)
        {
            Boolean show = false;
            Boolean enable = false;
            switch (state)
            {
                case ConnectionState.NONE:
                    show = true;
                    enable = true;
                    break;
                case ConnectionState.AUTH:
                    show = true;
                    enable = false;
                    break;
                case ConnectionState.DONE:
                    show = false;
                    enable = true;
                    break;
            }
            pnLogin.Visible = show;
            pnLogin.Enabled = enable;
            btLoginConnect.Text = (enable) ? "CONNECT" : "CONNECTING...";
            pnProcess.Visible = !show;
            miConnect.Enabled = enable;
            miConnect.Text = (show) ? "Connect" : "Disconnect";
            State = state;
        }

        private void miConnect_Click(object sender, EventArgs e)
        {
            if (miConnect.Text.Equals("Connect"))
            {
                Connect();
            }
            else
            {
                Disconnect();
            }
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void AdminPanelForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            return;
            if (State != ConnectionState.NONE)
            {
                DialogResult result = MessageBox.Show("Are you sure you want to exit the application?" + Environment.NewLine + 
                                                        "Any unsaved data will be lost!",
                                                        "Warning", 
                                                        MessageBoxButtons.YesNo, 
                                                        MessageBoxIcon.Warning, 
                                                        MessageBoxDefaultButton.Button2);
                e.Cancel = result == DialogResult.No;
            }
        }

        private void tbProcessFilter_TextChanged(object sender, EventArgs e)
        {
            String pattern = tbProcessFilter.Text;
            Regex validator = new Regex(pattern, RegexOptions.IgnoreCase);
            List<Record> users = new List<Record>(Database.Users);
            Int32 index = 0;
            while (index < users.Count)
            {
                if (!validator.IsMatch(users[index].Name))
                {
                    users.RemoveAt(index);
                }
                else
                {
                    ++index;
                }
            }
            UserlistFill(lvProcessUsers, users, Database.Ranks);
        }

        private void lvProcessUsers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvProcessUsers.SelectedItems.Count > 0)
            {
                SelectUser(lvProcessUsers.SelectedItems[0].Text);
            }
        }

        private void SelectUser(String username)
        {
            if (tcProcessProperties.SelectedTab == tpProcessSecurity)
            {
                SecurityData data = Database.GetSecurityData(username, Database.Users.Find(user => user.Name == username).ID);
                FillTextBox(tbProcessUsername, data.Username);
                FillTextBox(tbProcessPassword, data.Password);
                FillComboBox(cbProcessRanks, data.Rank);
                FillComboBox(cbProcessGenders, data.Gender);
                FillDateTime(dtProcessBirthday, data.Birthday);
                FillTextBox(tbProcessQuestion, data.Question);
                FillTextBox(tbProcessAnswer, data.Answer);
            }
        }

        private void FillTextBox(TextBox control, DataField<String> data)
        {
            //control.ReadOnly = !(Database.CanLook(data.Rights) && Database.CanModify(data.Rights));
            control.Text = (Database.CanLook(data.Rights)) ? data.Name : "";
        }

        private void FillComboBox(ComboBox control, DataField<String> data)
        {
            //control.Enabled = (Database.CanLook(data.Rights) && Database.CanModify(data.Rights));
            control.Text = (Database.CanLook(data.Rights)) ? data.Name : "";
        }

        private void FillDateTime(DateTimePicker control, DataField<DateTime> data)
        {
            //control.Enabled = !(Database.CanLook(data.Rights) && Database.CanModify(data.Rights));
            control.Text = (Database.CanLook(data.Rights)) ? data.Name.ToString() : control.MinDate.ToString();
        }
    }
}
